#ifndef __GfxDriver_GfxDriver_h__
#define __GfxDriver_GfxDriver_h__

#include "Core/BasicTypes.h"
#include "Core/Service.h"
#include "Core/StringUtil.h"
#include "GfxDriver/PrimitiveType.h"
#include "GfxDriver/DriverState.h"
#include "GfxDriver/PixelFormat.h"

namespace Orca {

	class VertexProgram;
	class FragmentProgram;
	class Shader;
	class Texture;
	class Texture2d;
	class TextureCube;
	class TextureRendered;
	class VertexBuffer;
	class VertexInput;
	class IndexBuffer;
	class DepthBuffer;
	class RenderTarget;

	//--------------------------------------------------------------------------
	class GfxDriver : public Service {

	public:
		ORCA_DECLARE_SERVICE()

		virtual ~GfxDriver() {}

		virtual void resetErrors() = 0;

		virtual void clearFrameBuf(const vec4 &value) = 0;
		virtual void clearDepthBuf(float value) = 0;
		virtual void clearStencilBuf(uint32 value) = 0;
		virtual void clearAllBufs(const vec4 &clr, float depth, uint32 stencil) = 0;

		virtual VertexProgram* createVertexProgram(const uint8* data) = 0;
		virtual FragmentProgram* createFragmentProgram(const uint8* data) = 0;
		virtual Shader* createShader(VertexProgram *vp, FragmentProgram *fp) = 0;

		virtual Texture2d* create2DTexture(uint32 w, uint32 h, PixelFormat format) = 0;
		virtual TextureCube* createCubeTexture(uint32 size, PixelFormat format) = 0;
		virtual TextureRendered* createRenderedTexture(uint32 w, uint32 h, PixelFormat format) = 0;
		
		virtual VertexBuffer* createVertexBuffer(uint32 sizeInBytes, bool staticUsage) = 0;
		virtual VertexInput* createVertexInput() = 0;
		virtual IndexBuffer* createIndexBuffer(uint32 sizeInBytes, bool staticUsage) = 0;

		virtual RenderTarget* createRenderTarget() = 0;
		virtual DepthBuffer* createDepthBuffer(
			 uint32 width
			,uint32 height
			,uint32 depthBits
			,uint32 stencilBits) = 0;

		virtual bool bindRenderTarget(RenderTarget *renderTarget) = 0;
		
		virtual bool bindTexture(uint32 channel, Texture *tex) = 0;

		virtual void setViewport(uint32 x, uint32 y, uint32 width, uint32 height) = 0;
		virtual bool beginRender() = 0;
		virtual void endRender() = 0;

		virtual bool beginDrawing(VertexInput *vertexInput) = 0;
		virtual void draw(PrimitiveType primType, uint32 startVertex, uint32 primCnt) = 0;
		virtual void drawIndexed(PrimitiveType primType, uint32 startIndex, uint32 primCnt) = 0;
		virtual void endDrawing() = 0;

		virtual void setCullMode(CullMode cullMode) = 0;

		virtual void setDepthTestEnable(bool enable) = 0;
		virtual void setDepthTestFunc(CmpFunc cmp) = 0;
		virtual void setDepthWriteEnable(bool enable) = 0;

		virtual void setAlphaBlendEnable(bool enable) = 0;
		virtual void setSeperatedAlphaBlendEnable(bool enable) = 0;
		virtual void setAlphaBlendColorFactor(BlendFactor srcFactor, BlendFactor destFactor) = 0;
		virtual void setAlphaBlendAlphaFactor(BlendFactor srcFactor, BlendFactor destFactor) = 0;

		virtual void setAlphaTestEnable(bool enable) = 0;
		virtual void setAlphaTestFunc(CmpFunc cmp, float refValue) = 0;

		virtual void setWorldTransform(const mtx44 &mtx) = 0;
		virtual void setViewTransform(const mtx44 &mtx) = 0;
		virtual void setProjTransform(const mtx44 &mtx) = 0;
	};

}

#endif	// __GfxDriver_GfxDriver_h__